
package JET.SA;

import JET.Centers.ControlCenter;
import JET.Centers.Graphics.GUICenter.UtilTabs;
import JET.Frames.DataModels.DataModelsFactory;
import JET.Frames.DataModels.SceneTreeModel;
import JET.Scene;
import JET.UtilPanels.UPSceneInspector;
import JET.geom.Vec2d;
import JET.physics.Mass;
import JET.physics.RSpring;
import JET.physics.Spring;
import JET.physics.Wall;
import JET.physics.bodies.SpringBody;
import JET.physics.interfaces.SceneTreeNode;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.tree.TreePath;

/**
 *
 * @author 057Ry
 */
public class SA_SpringBody {

    static final ControlCenter CC = ControlCenter.getInstance();
    
    ////////////////////////////////////////////////////////////////////////////
    //                        S P R I N G   B O D Y                           //
    ////////////////////////////////////////////////////////////////////////////

    public static SpringBody addSpringBodyToScene(Scene scene, boolean updateSceneTreeSelection) {
        SpringBody sb = new SpringBody();
        scene.getJETContext().addSpringBody(sb);

        if (updateSceneTreeSelection) DataModelsFactory.getSceneTreeModel().fireSpringBodyListChanged();
        SA_SpringBody.setCurrentSpringBody(sb, scene, updateSceneTreeSelection);

        return sb;
    }

    public static SpringBody addSpringBodyToScene(SpringBody sb, Scene scene, boolean updateSceneTreeSelection) {
        if (sb != null) {
            //scene.getEngine().addSpringBody(sb);
            scene.getJETContext().addSpringBody(sb);
            if (updateSceneTreeSelection) DataModelsFactory.getSceneTreeModel().fireSpringBodyListChanged();
            SA_SpringBody.setCurrentSpringBody(sb, scene, updateSceneTreeSelection);
            return sb;
        } else {
            return null;
        }
    }

    public static void removeSpringBody(SpringBody sb, Scene scene) {
        if (sb != null) {
            // Removeing Walls from selection
            for (Wall wall : sb.getBorder().getWallList()) {
                if (scene.EC.selectionGroup.getWallList().contains(wall)) {
                    SA_Selection.removeWallFromSelection(wall, scene, true);
                }
            }

            // Removeing Springs from selection
            for (Spring spring : sb.getSpringList()) {
                if (scene.EC.selectionGroup.getSpringList().contains(spring)) {
                    SA_Selection.removeSpringFromSelection(spring, scene, true);
                }
            }

            // Removeing Rotary Springs from selection
            for (RSpring rSpring : sb.getRSpringList()) {
                if (scene.EC.selectionGroup.getRSpringList().contains(rSpring)) {
                    SA_Selection.removeRSpringFromSelection(rSpring, scene, true);
                }
            }

            // Removeing masses from selection
            Collection<Mass> massCol = sb.getMassListSync();
            synchronized(massCol) {
                for (Mass mass : massCol) {
                    if (scene.EC.selectionGroup.getMassList().contains(mass)) {
                        SA_Selection.removeMassFromSelection(mass, scene, true);
                    }
                }
            }

            // Remove spring body from engine
            scene.getJETContext().removeSpringBody(sb);

            // If thera are no more spring bodies in the endgine do apropriate stuff with editor
            if (scene.getJETContext().getSpringBodyList().isEmpty()) {
                SpringBody.zeroSBCount();
                SA_SpringBody.setCurrentSpringBody(null, scene, true);
            } // In other case, set next sb to be actual spring body that editor works on
            else {
                SpringBody asb = scene.getJETContext().getSpringBodyList().get(scene.getJETContext().getSpringBodyList().size() - 1);
                SA_SpringBody.setCurrentSpringBody(asb, scene, true);
            }

        }
    }

    public synchronized static void flipSpringBodyHorizontally(SpringBody sb) {
        Vec2d cv = sb.getCenterVec();
        Collection<Mass> massCol = sb.getMassListSync();
        synchronized(massCol) {
            for (Mass mass : massCol) {
                double dx = (cv.getX() - mass.getPosition().getX()) * 2.;
                mass.getPosition().addX(dx);
                mass.getForce().scaleX(-1);
                mass.getVelocity().scaleX(-1);
            }
        }
    }

    public synchronized static void flipSpringBodyVertically(SpringBody sb) {
        Vec2d cv = sb.getCenterVec();
        Collection<Mass> massCol = sb.getMassListSync();
        synchronized(massCol) {
            for (Mass mass : massCol) {
                double dy = (cv.getY() - mass.getPosition().getY()) * 2.;
                mass.getPosition().addY(dy);
                mass.getForce().scaleY(-1);
                mass.getVelocity().scaleY(-1);
            }
        }
    }

    public synchronized static void rotateSpringBodyByAngle(SpringBody sb, double a) {
        Mass tmpMass = new Mass(0, 0, 0);
        Vec2d cv = sb.getCenterVec();

        Collection<Mass> massCol = sb.getMassListSync();
        synchronized(massCol) {
            for (Mass mass : massCol) {
                tmpMass.become(mass);
                tmpMass.getPosition().sub(cv);
                tmpMass.getPosition().rotate(a);
                tmpMass.getPosition().add(cv);
                mass.getPosition().become(tmpMass.getPosition());
            }
        }
    }

    public synchronized static SpringBody setCurrentSpringBody(SpringBody sb, Scene scene, boolean updateSceneTreeSelection) {
        // Unselect actual spring body scene tree node
        if (scene.EC.currentBody!=null && updateSceneTreeSelection) {
            UPSceneInspector upSceneInspector = (UPSceneInspector) CC.GUIC.getUtilTab(UtilTabs.SceneInspector);
            //SceneTreeNode node = scene.getEngine().sceneTreeNode;
            SceneTreeNode node = DataModelsFactory.getSceneTreeModel().sceneRootNode;
            TreePath path = new TreePath(new Object[]{  node,
                                                        node.getChild(SceneTreeModel.SceneRootNode.NODE_INDEX_SPRING_BODIES),
                                                        scene.EC.currentBody
                                                 });
            upSceneInspector.getSceneTree().removeSelectionPath(path);
        }

        scene.EC.currentBody = sb;

        if (sb != null) {
            SA_Dialogs.fillPropertiesDialogWithSpringBodyData(sb);
            sb.updateBoundingArea();
            if (CC.GUIC.materialsDialog!=null)
                CC.GUIC.materialsDialog.setSelectedCell(sb.getMaterial(), sb.getMaterial());

            if (updateSceneTreeSelection) {
                UPSceneInspector upSceneInspector = (UPSceneInspector) CC.GUIC.getUtilTab(UtilTabs.SceneInspector);
                //SceneTreeNode node = scene.getEngine().sceneTreeNode;
                SceneTreeNode node = DataModelsFactory.getSceneTreeModel().sceneRootNode;
                TreePath path = new TreePath(new Object[]{  node,
                                                            node.getChild(SceneTreeModel.SceneRootNode.NODE_INDEX_SPRING_BODIES),
                                                            sb
                                                     });
                //upSceneInspector.getSceneTree().addSelectionPath(path);
            }

            CC.GUIC.repaintAllSceneTabs();
        }

        return sb;
    }

    public synchronized static SpringBody setActualSpringBody(int index, Scene scene, boolean updateSceneTreeSelection) {
        SpringBody sb = null;

        if (index >= 0 && index < scene.getJETContext().getSpringBodyList().size()) {
            sb = scene.getJETContext().getSpringBodyList().get(index);
        }

        if (sb != null) {
            scene.EC.currentBody = sb;
            SA_Dialogs.fillPropertiesDialogWithSpringBodyData(sb);
            CC.GUIC.materialsDialog.setSelectedCell(sb.getMaterial(), sb.getMaterial());

            if (updateSceneTreeSelection) {
                UPSceneInspector upSceneInspector = (UPSceneInspector) CC.GUIC.getUtilTab(UtilTabs.SceneInspector);
                //SceneTreeNode node = scene.getEngine().sceneTreeNode;
                SceneTreeNode node = DataModelsFactory.getSceneTreeModel().sceneRootNode;
                TreePath path = new TreePath(new Object[]{  node,
                                                            node.getChild(SceneTreeModel.SceneRootNode.NODE_INDEX_SPRING_BODIES),
                                                            sb
                                                     });
                upSceneInspector.getSceneTree().addSelectionPath(path);
            }
        }

        return sb;
    }

    public synchronized static void setSpringBodyName(SpringBody sb, String name, boolean updateSceneTreeSelection) {
        sb.setName(name);
        if (updateSceneTreeSelection)
            DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged(sb);
        CC.GUIC.repaintAllSceneTabs();
    }

    public static void clearSpringBodies(Scene scene, boolean updateSceneTreeSelection) {
        ArrayList<SpringBody> list = new ArrayList<SpringBody>(scene.getJETContext().getSpringBodyList());
        for (SpringBody sb : list) {
            SA_SpringBody.removeSpringBody(sb, scene);
        }
        list.clear();

        if (updateSceneTreeSelection)
            DataModelsFactory.getSceneTreeModel().fireSpringBodyListChanged();
    }
}
